Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Right/left/Cross/Indexed Joins and Implement Table Edit Accumulator #596

Merged
merged 25 commits into from
Oct 26, 2021

Conversation

VinaiRachakonda
Copy link
Contributor

@VinaiRachakonda VinaiRachakonda commented Oct 21, 2021

  1. Add functionality for updates to work with Indexed Joins
  2. Implement a Table Edit Accumulator that writes changes at Close time
  3. Fix some undefined test cases
  4. Add functionality for Update Join w/ Right,Left,Cross joins

@VinaiRachakonda VinaiRachakonda changed the title [WIP] Updated Join with Indexes Updated Join with Indexes and Implement Table Edit Accumulator Oct 22, 2021

// Get implements the tableEditAccumulator interface.
func (k *keylessTableEditAccumulator) Get(value sql.Row) (sql.Row, bool, bool, error) {
// Note: Keyless tables do not have to return an accurate answer here as any given row can be inserted or deleted
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this tbh but I also don't like adding conditional logic in table.go for checking this condition. Maybe implement a keyless table implementation as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just punt for now

@VinaiRachakonda VinaiRachakonda changed the title Updated Join with Indexes and Implement Table Edit Accumulator Add Right/left/Cross/Indexed Joins and Implement Table Edit Accumulator Oct 25, 2021
Copy link
Member

@zachmu zachmu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is ready to go, nice work.

The main request I have is to follow up after this goes in to do something different for the JoinSorter node.

@@ -261,6 +261,110 @@ var UpdateTests = []WriteQueryTest{
sql.NewRow(1, 1, 32, 31, 32, 33, 34),
},
},
{
WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 INNER JOIN two_pk a1 on one_pk.pk = two_pk.pk2 SET two_pk.c1 = two_pk.c1 + 1`, // cross join
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not verifying these query results by hand, make sure you have (or tested them on mysql)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a cross join (a cross join has no join condition)(

},
},
{
WriteQuery: `UPDATE othertable INNER JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, // cross join
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a cross join but not phrased as on

A cross join has no join condition

This just reduces to a cross join because the analyzer realizes that none of the join predicates are actually join predicates to moves them to the filter.

You should keep this test and add another one that is an explicit cross join

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should make sure you have tests for the implicit cross join, e.g.

update table1, table2 set...

ExpectedErr: sql.ErrUnsupportedFeature,
},
}
var UpdateErrorTests = []QueryErrorTest{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete this now it's empty?

memory/table.go Outdated
return err
}

t.table = tbl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't need to do this, you won't be reusing this object after close is called

memory/table.go Outdated
for _, i := range pkColIdxes {
vals[i] = row[pkColIdxes[i]]
}
return sql.NewUniqueKeyErr(fmt.Sprint(vals), true, partitionRow)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have engine tests for this?

(We don't, they wouldn't have passed before)

return nil
}

// insertHelper deletes a row from a keyless table, if it exists.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment wrong

// insertHelper deletes a row from a keyless table, if it exists.
func (k *keylessTableEditAccumulator) insertHelper(ctx *sql.Context, table *Table, row sql.Row) error {
key := string(table.keys[table.insert])
table.insert++
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

table.insert should be called table.insertPartIdx or similar

func (k *keylessTableEditAccumulator) insertHelper(ctx *sql.Context, table *Table, row sql.Row) error {
key := string(table.keys[table.insert])
table.insert++
if table.insert == len(table.keys) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

table.keys should be called table.partitionKeys

if jn == nil {
return n, nil
if unsupported {
return nil, sql.ErrUnsupportedFeature.New()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still possible? Didn't you remove all the test cases that might trigger this?


// IndexedJoinSorter is used to sort the output of an IndexedJoin to fit the original join order. Note that this
// occurs because IndexedJoins use join optimization logic that changes the original given join order.
type IndexedJoinSorter struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I don't like this solution, although you can check it in for the time being as long as you follow up with a fix.

This is basically just a projection (mapping from one column order to another), not a new kind of node that we should have to account for separately everywhere (which will be prone to bugs). I think the only reason this works is that it's applied in the join optimization step, which happens last. Otherwise the new node type would cause issues (lots of case statements to clean up).

So you have two choices: either replace this with a straight projection (easy enough).

Or put the projection into the UpdateJoin node itself (probably better).

But either way, definitely don't introduce a new node type here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah 100% makes sense. Will followup with a new pr.

@VinaiRachakonda VinaiRachakonda merged commit 950fb2e into main Oct 26, 2021
@Hydrocharged Hydrocharged deleted the vinai/additional-update-join-support branch December 8, 2021 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants